package com.fy.service.impl;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fy.common.constants.KeysConstant;
import com.fy.mapper.ActivityMapper;
import com.fy.mapper.AnnouncementMapper;
import com.fy.pojo.dto.activity.*;
import com.fy.pojo.entity.Activity;
import com.fy.pojo.vo.activity.ActivityListVO;
import com.fy.pojo.vo.activity.ActivityStatisticsVO;
import com.fy.pojo.vo.activity.ActivityVO;
import com.fy.service.ActivityService;
import com.fy.utils.ActivityStatusUtil;
import com.fy.utils.DateFormatter;
import com.fy.utils.StringTools;
import com.fy.utils.aliyunUtils.AliOssFileOperation;
import com.fy.utils.fileUtils.FileUploadTool;
import com.fy.utils.result.PageResult;
import com.fy.utils.result.Result;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Slf4j
@Service
public class ActivityServiceImpl extends ServiceImpl<ActivityMapper, Activity> implements ActivityService {

    @Autowired
    private FileUploadTool fileUploadTool;

    @Autowired
    private AnnouncementMapper announcementMapper;

    @Autowired
    private AliOssFileOperation aliOssFileOperation;

    @Autowired
    private ActivityMapper activityMapper;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private ObjectMapper objectMapper;

    private static final String ACTIVITY_LIST_KEY = "activity:list";
    private static final String ACTIVITY_LOCK_KEY = "activity:lock:list";
    private static final long LOCK_WAIT_TIME = 3; // 等待锁的时间
    private static final long LOCK_LEASE_TIME = 10; // 锁的持有时间

    /**
     * 从Redis获取活动列表，如果不存在则加锁从DB获取
     */
    private List<Activity> getActivitiesWithCache() {
        try {
            // 先清除之前的缓存
            redisTemplate.delete(ACTIVITY_LIST_KEY);

            // 从数据库获取
            List<Activity> activities = this.list();
            if (!activities.isEmpty()) {
                // 存入Redis
                redisTemplate.opsForValue().set(ACTIVITY_LIST_KEY, activities, 1, TimeUnit.HOURS);
            }
            return activities;
        } catch (Exception e) {
            log.error("获取活动列表失败", e);
            throw new RuntimeException("获取活动列表失败");
        }
    }

    /**
     * 清除Redis缓存
     */
    private void clearCache() {
        try {
            redisTemplate.delete(KeysConstant.ACTIVITY_LIST_KEY);
            log.info("清除活动缓存成功");
        } catch (Exception e) {
            log.error("清除活动缓存失败", e);
            // 这里不抛异常，避免影响主流程
        }
    }

    @Override
    @Transactional
    public Result publishActivity(ActivityDTO activityDTO) {
        log.info("开始发布活动，活动信息：{}", activityDTO);

        try {
            // 1. 参数校验
            if (activityDTO.getStartTime() == null || activityDTO.getEndTime() == null) {
                return Result.error("活动时间不能为空");
            }

            if (activityDTO.getEndTime().before(activityDTO.getStartTime())) {
                return Result.error("结束时间不能早于开始时间");
            }

            if (StringUtils.isBlank(activityDTO.getTitle())) {
                return Result.error("活动标题不能为空");
            }

            if (StringUtils.isBlank(activityDTO.getType())) {
                return Result.error("活动类型不能为空");
            }

            // 2. DTO转换为实体
            Activity activity = new Activity();
            BeanUtils.copyProperties(activityDTO, activity);

            // 4. 设置创建和更新时间
            LocalDateTime now = LocalDateTime.now();
            activity.setCreateTime(now);
            activity.setUpdateTime(now);

            // 5. 保存活动
            int rows = activityMapper.insert(activity);
            if (rows <= 0) {
                return Result.error("活动发布失败");
            }

            log.info("活动发布成功，活动ID：{}", activity.getId());
            return Result.success("活动发布成功");

        } catch (IllegalArgumentException e) {
            log.error("时间格式转换异常", e);
            return Result.error("时间格式不正确：" + e.getMessage());
        } catch (Exception e) {
            log.error("活动发布异常", e);
            return Result.error("活动发布失败：" + e.getMessage());
        }
    }

    @Override
    public Result getActivityList(ActiveListQueryDTO queryDTO) {
        try {
            // 1. 获取带缓存的活动列表
            List<Activity> allActivities = getActivitiesWithCache();

            // 2. 在内存中过滤
            Stream<Activity> stream = allActivities.stream();

            if (StringUtils.isNotBlank(queryDTO.getTitle())) {
                stream = stream.filter(a -> a.getTitle().contains(queryDTO.getTitle()));
            }
            if (StringUtils.isNotBlank(queryDTO.getType())) {
                stream = stream.filter(a -> queryDTO.getType().equals(a.getType()));
            }

            // 3. 排序
            stream = stream.sorted(Comparator.comparing(Activity::getCreateTime).reversed());

            // 4. 分页
            List<Activity> filteredList = stream
                    .skip((queryDTO.getPageNum() - 1) * queryDTO.getPageSize())
                    .limit(queryDTO.getPageSize())
                    .collect(Collectors.toList());

            // 5. 转换为VO
            List<ActivityVO> activityVOList = filteredList.stream()
                    .map(activity -> {
                        ActivityVO vo = new ActivityVO();
                        BeanUtils.copyProperties(activity, vo);
                        vo.setStartTime(DateFormatter.getTimestampStringByDate(activity.getStartTime()));
                        vo.setEndTime(DateFormatter.getTimestampStringByDate(activity.getEndTime()));
                        return vo;
                    })
                    .collect(Collectors.toList());

            PageResult pageResult = new PageResult();
            pageResult.setList(activityVOList);
            pageResult.setPageNo(queryDTO.getPageNum());
            pageResult.setPageSize(queryDTO.getPageSize());
            pageResult.setTotalCount((long) allActivities.size());

            return Result.success(pageResult);
        } catch (Exception e) {
            log.error("查询活动列表异常", e);
            return Result.error(e.getMessage());
        }
    }

    @Override
    public Result<PageResult> getActivityListForUser(ActivityListDTO queryDTO) {
        try {
            // 1. 获取带缓存的活动列表
            List<Activity> allActivities = getActivitiesWithCache();

            // 2. 在内存中过滤
            Stream<Activity> stream = allActivities.stream();

            if (StringUtils.isNotBlank(queryDTO.getCategory()) && !"all".equals(queryDTO.getCategory())) {
                stream = stream.filter(a -> queryDTO.getCategory().equals(a.getType()));
            }

            // 3. 排序
            stream = stream.sorted(Comparator.comparing(Activity::getStartTime).reversed());

            // 4. 分页
            List<Activity> filteredList = stream
                    .skip((queryDTO.getPageNo() - 1) * queryDTO.getPageSize())
                    .limit(queryDTO.getPageSize())
                    .collect(Collectors.toList());

            // 5. 转换为VO
            List<ActivityListVO> voList = filteredList.stream()
                    .map(activity -> {
                        ActivityListVO vo = new ActivityListVO();
                        BeanUtils.copyProperties(activity, vo);
                        vo.setStartTime(DateFormatter.getTimestampStringByDate(activity.getStartTime()));
                        vo.setEndTime(DateFormatter.getTimestampStringByDate(activity.getEndTime()));
                        return vo;
                    })
                    .collect(Collectors.toList());

            PageResult pageResult = new PageResult();
            pageResult.setList(voList);
            pageResult.setPageNo(queryDTO.getPageNo());
            pageResult.setPageSize(queryDTO.getPageSize());
            pageResult.setTotalCount((long) allActivities.size());

            return Result.success(pageResult);
        } catch (Exception e) {
            log.error("查询用户端活动列表异常", e);
            return Result.error(e.getMessage());
        }
    }

    @Override
    public Result getActivityListAll(ActivityListDTO queryDTO) {
        try {
            // 1. 获取带缓存的活动列表
            List<Activity> allActivities = getActivitiesWithCache();

            // 2. 转换为VO并添加状态
            List<ActivityVO> activityVOList = allActivities.stream()
                    .map(activity -> {
                        ActivityVO vo = new ActivityVO();
                        BeanUtils.copyProperties(activity, vo);
                        Timestamp startTime = activity.getStartTime();
                        Timestamp endTime = activity.getEndTime();
                        vo.setActivityStatus(ActivityStatusUtil.determineStatus(startTime, endTime));
                        vo.setStartTime(DateFormatter.getTimestampStringByDate(startTime));
                        vo.setEndTime(DateFormatter.getTimestampStringByDate(endTime));
                        return vo;
                    })
                    .collect(Collectors.toList());

            PageResult pageResult = new PageResult();
            pageResult.setList(activityVOList);
            pageResult.setPageNo(queryDTO.getPageNo());
            pageResult.setPageSize(queryDTO.getPageSize());
            pageResult.setTotalCount((long) activityVOList.size());

            return Result.success(pageResult);
        } catch (Exception e) {
            log.error("获取全部活动列表异常", e);
            return Result.error(e.getMessage());
        }
    }

    /**
     * 获取活动统计
     *
     * @return
     */
    @Override
    public ActivityStatisticsVO getStatistics() {
        ActivityStatisticsVO activityStatisticsVO = new ActivityStatisticsVO();
        List<Activity> activityList = activityMapper.selectList(null);
        activityStatisticsVO.setAllAnnouncement(announcementMapper.selectList(null).size());
        activityStatisticsVO.setTotal(activityList.size());
        activityStatisticsVO.setOngoing((int) activityList.stream().filter(activity -> {
            Timestamp now = new Timestamp(System.currentTimeMillis());
            return now.before(activity.getEndTime());
        }).count());

        int participantCounts = 0;
        for (Activity activity : activityList) {
            if (activity.getJoinCount() != null) {
                participantCounts = (int) (participantCounts + activity.getJoinCount());
            }
        }
        activityStatisticsVO.setParticipantCounts(participantCounts);
        // 所有活动的pointsReward的值总和赋给activityStatisticsVO.setRewards();
        int rewards = 0;
        for (Activity activity : activityList) {
            if (activity.getPointsReward() != null) {
                rewards = rewards + activity.getPointsReward();
            }
        }
        activityStatisticsVO.setRewards(rewards);

        return activityStatisticsVO;
    }

    /**
     * 更新活动
     *
     * @param updateActivityDTO 更新活动信息
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result updateActivity(UpdateActivityDTO updateActivityDTO) {
        try {
            // 1. 参数校验
            if (updateActivityDTO.getId() == null) {
                return Result.error("活动ID不能为空");
            }

            // 2. 检查活动是否存在
            Activity activity = activityMapper.selectById(updateActivityDTO.getId());
            if (activity == null) {
                return Result.error("活动不存在");
            }

            // 3. 更新活动信息
            Activity updateActivity = new Activity();
            BeanUtils.copyProperties(updateActivityDTO, updateActivity);
            updateActivity.setUpdateTime(LocalDateTime.now());

            // 4. 执行更新
            int rows = activityMapper.updateById(updateActivity);
            if (rows > 0) {
                clearCache();
                return Result.success("活动更新成功");
            } else {
                return Result.error("活动更新失败");
            }
        } catch (Exception e) {
            log.error("更新活动失败", e);
            return Result.error("更新活动失败：" + e.getMessage());
        }
    }

    /**
     * 添加活动
     * 
     * @param addActivityDTO 活动信息
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result addActivity(AddActivityDTO addActivityDTO) {
        try {
            // 1. 参数校验
            if (StringUtils.isBlank(addActivityDTO.getTitle())) {
                return Result.error("活动标题不能为空");
            }
            if (StringUtils.isBlank(addActivityDTO.getType())) {
                return Result.error("活动类型不能为空");
            }
            if (StringUtils.isBlank(addActivityDTO.getStartTime())
                    || StringUtils.isBlank(addActivityDTO.getEndTime())) {
                return Result.error("活动时间不能为空");
            }

            // 2. 转换为实体
            Activity activity = new Activity();
            BeanUtils.copyProperties(addActivityDTO, activity);

            // 3. 处理时间
            try {
                activity.setStartTime(Timestamp.valueOf(addActivityDTO.getStartTime()));
                activity.setEndTime(Timestamp.valueOf(addActivityDTO.getEndTime()));
            } catch (IllegalArgumentException e) {
                return Result.error("时间格式不正确");
            }

            // 4. 设置创建和更新时间
            LocalDateTime now = LocalDateTime.now();
            activity.setCreateTime(now);
            activity.setUpdateTime(now);

            // 5. 设置初始参与次数
            activity.setJoinCount(0L);

            // 6. 保存活动
            boolean success = save(activity);
            if (success) {
                clearCache();
                return Result.success("活动添加成功");
            } else {
                return Result.error("活动添加失败");
            }
        } catch (Exception e) {
            log.error("添加活动失败", e);
            throw new RuntimeException("添加活动失败：" + e.getMessage());
        }
    }

    /**
     * 上传封面
     * 
     * @param file
     * @param id
     * @return
     */
    @Override
    public String uploadCoverFile(int id, MultipartFile file) {

        Activity activity = activityMapper.selectById(id);
        if (activity != null && activity.getCover() != null) {
            aliOssFileOperation.deleteFile(StringTools.getFileNameFromUrl(activity.getCover()));
        }
        String url = fileUploadTool.uploadFile(file);
        activity.setCover(url);
        this.updateById(activity);
        clearCache();
        return url;
    }

    // 管理员操作方法，更新后清除缓存
    @Transactional(rollbackFor = Exception.class)
    public Result deleteActivity(Long id) {
        try {
            activityMapper.deleteById(id);
            clearCache();
            return Result.success();
        } catch (Exception e) {
            log.error("删除活动失败", e);
            throw new RuntimeException("删除活动失败", e);
        }
    }
}